home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / pmodules.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  44KB  |  1,189 lines

  1. {
  2.     $Id: pmodules.pas,v 1.2.2.6 1998/09/14 18:58:09 carl Exp $
  3.     Copyright (c) 1998 by Florian Klaempfl
  4.  
  5.     Handles the parsing and loading of the modules (ppufiles)
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. unit pmodules;
  24.  
  25.   interface
  26.  
  27.     uses
  28.        dos,strings,
  29.        cobjects,globals,scanner,symtable,aasm,tree,pass_1,
  30.        types,hcodegen,files,verbose,systems,link,assemble
  31. {$ifdef GDB}
  32.        ,gdb
  33. {$endif GDB}
  34.        { parser specific stuff }
  35.        ,pbase,pdecl,pstatmnt,psub
  36.        { processor specific stuff }
  37. {$ifdef i386}
  38.        ,i386
  39.        ,cgai386
  40.        ,tgeni386
  41.        ,cgi386
  42.        ,aopt386
  43. {$endif}
  44. {$ifdef m68k}
  45.        ,m68k
  46.        ,cga68k
  47.        ,tgen68k
  48.        ,cg68k
  49. {$endif}
  50.        ;
  51.  
  52.     function loadunit(const s : string;compile_system, in_uses : boolean) : pmodule;
  53.     procedure proc_unit;
  54.     procedure proc_program(islibrary : boolean);
  55.  
  56.   implementation
  57.  
  58.     uses
  59.        parser;
  60.  
  61.     {$I innr.inc}
  62.  
  63.     procedure insertinternsyms(p : psymtable);
  64.  
  65.       begin
  66.          p^.insert(new(psyssym,init('CONCAT',in_concat_x)));
  67.          p^.insert(new(psyssym,init('WRITE',in_write_x)));
  68.          p^.insert(new(psyssym,init('WRITELN',in_writeln_x)));
  69.          p^.insert(new(psyssym,init('ASSIGNED',in_assigned_x)));
  70.          p^.insert(new(psyssym,init('READ',in_read_x)));
  71.          p^.insert(new(psyssym,init('READLN',in_readln_x)));
  72.          p^.insert(new(psyssym,init('OFS',in_ofs_x)));
  73.          p^.insert(new(psyssym,init('SIZEOF',in_sizeof_x)));
  74.          p^.insert(new(psyssym,init('TYPEOF',in_typeof_x)));
  75.          p^.insert(new(psyssym,init('LOW',in_low_x)));
  76.          p^.insert(new(psyssym,init('HIGH',in_high_x)));
  77.          p^.insert(new(psyssym,init('SEG',in_seg_x)));
  78.          p^.insert(new(psyssym,init('ORD',in_ord_x)));
  79.          p^.insert(new(psyssym,init('PRED',in_pred_x)));
  80.          p^.insert(new(psyssym,init('SUCC',in_succ_x)));
  81.  
  82.          { for testing purpose }
  83.          p^.insert(new(psyssym,init('DECI',in_dec_x)));
  84.          p^.insert(new(psyssym,init('INCI',in_inc_x)));
  85.          p^.insert(new(psyssym,init('STR',in_str_x_string)));
  86.       end;
  87.  
  88.     procedure load_ppu(oldhp,hp : pmodule;compile_system : boolean);
  89.  
  90.       var
  91.          loaded_unit  : pmodule;
  92.          b            : byte;
  93.          checksum,
  94.          count,
  95.          nextmapentry : longint;
  96.          hs           : string;
  97.          w1,w2        : word;
  98.       begin
  99.          { init the map }
  100.          new(hp^.map);
  101.          nextmapentry:=1;
  102.  
  103.          { load the used units from interface }
  104.          hp^.ppufile^.read_data(b,1,count);
  105.          while (b=ibloadunit) do
  106.            begin
  107.               { read unit name }
  108.               hp^.ppufile^.read_data(hs[0],1,count);
  109.               hp^.ppufile^.read_data(hs[1],byte(hs[0]),count);
  110.               hp^.ppufile^.read_data(checksum,4,count);
  111. {$ifdef BIG_ENDIAN}
  112.               w1:=checksum and $ffff;
  113.               w2:=checksum shr 16;
  114.               checksum:=swap(w2)+(longint(swap(w1)) shl 16);
  115. {$endif}
  116.               loaded_unit:=loadunit(hs,false,false);
  117.               if hp^.compiled then
  118.                 exit;
  119.               { if the crc of a used unit is the same as }
  120.               { written to the PPU file, we needn't to   }
  121.               { recompile the current unit               }
  122.               if (loaded_unit^.crc<>checksum) or
  123.                  (do_build and loaded_unit^.sources_avail) then
  124.                 begin
  125.                    { we have to compile the current unit }
  126.                    { remove stuff which isn't needed     }
  127.                    { forget the map }
  128.                    dispose(hp^.map);
  129.                    hp^.map:=nil;
  130.                    hp^.ppufile^.close;
  131.                    dispose(hp^.ppufile,done);
  132.                    hp^.ppufile:=nil;
  133.                    if assigned(oldhp^.current_inputfile) then
  134.                      oldhp^.current_inputfile^.tempclose;
  135.                    compile(hp^.mainsource^,compile_system);
  136.                    if (not oldhp^.compiled) and assigned(oldhp^.current_inputfile) then
  137.                      oldhp^.current_inputfile^.tempreopen;
  138.                    exit;
  139.                 end;
  140.               { setup the map entry for deref }
  141.               hp^.map^[nextmapentry]:=loaded_unit^.symtable;
  142.               inc(nextmapentry);
  143.  
  144.               if nextmapentry>maxunits then
  145.                Message(unit_f_too_much_units);
  146.  
  147.               { read until ibend }
  148.               hp^.ppufile^.read_data(b,1,count);
  149.            end;
  150.  
  151.          { ok, now load the unit }
  152.          hp^.symtable:=new(punitsymtable,load(hp^.unitname^));
  153.  
  154.          { if this is the system unit insert the intern }
  155.          { symbols                                      }
  156.          if compile_system then
  157.            insertinternsyms(psymtable(hp^.symtable));
  158.  
  159.          { now only read the implementation part }
  160.          hp^.in_implementation:=true;
  161.  
  162.          { load the used units from implementation }
  163.          hp^.ppufile^.read_data(b,1,count);
  164.          while (b<>ibend) and (b=ibloadunit) do
  165.            begin
  166.               { read unit name }
  167.               hp^.ppufile^.read_data(hs[0],1,count);
  168.               hp^.ppufile^.read_data(hs[1],byte(hs[0]),count);
  169.               hp^.ppufile^.read_data(checksum,4,count);
  170.               loaded_unit:=loadunit(hs,false,false);
  171.               if hp^.compiled then exit;
  172.               { if the crc of a used unit is the same as }
  173.               { written to the PPU file, we needn't to   }
  174.               { recompile the current unit               }
  175.               { but for the implementation part          }
  176.               { the written crc is false, because        }
  177.               { not defined when writing the ppufile !!  }
  178.               if {(loaded_unit^.crc<>checksum) or}
  179.                 (do_build and loaded_unit^.sources_avail) then
  180.                 begin
  181.                    { we have to compile the current unit }
  182.                    { remove stuff which isn't needed     }
  183.                    { forget the map }
  184.                    dispose(hp^.map);
  185.                    hp^.map:=nil;
  186.                    hp^.ppufile^.close;
  187.                    dispose(hp^.ppufile,done);
  188.                    hp^.ppufile:=nil;
  189.                    if not(hp^.sources_avail) then
  190.                     Message1(unit_f_cant_compile_unit,hp^.unitname^)
  191.                    else
  192.                      begin
  193.                         oldhp^.current_inputfile^.tempclose;
  194.                         compile(hp^.mainsource^,compile_system);
  195.                         oldhp^.current_inputfile^.tempclose;
  196.                      end;
  197.                    exit;
  198.                 end;
  199.               { read until ibend }
  200.               hp^.ppufile^.read_data(b,1,count);
  201.            end;
  202.          hp^.ppufile^.close;
  203.          dispose(hp^.map);
  204.          hp^.map:=nil;
  205.       end;
  206.  
  207.  
  208.     function loadunit(const s : string;compile_system, in_uses : boolean) : pmodule;
  209.  
  210.       var
  211.          st : punitsymtable;
  212.          old_current_module,hp,nextmodule : pmodule;
  213.          pu : pused_unit;
  214.          a  : pasmfile;
  215.          hs : pstring;
  216.          i  : longint;
  217.       begin
  218.          old_current_module:=current_module;
  219.          { be sure not to mix lines from different files }
  220.          { update_line; }
  221.          { unit not found }
  222.          st:=nil;
  223.          { search all loaded units }
  224.          hp:=pmodule(loaded_units.first);
  225.          while assigned(hp) do
  226.            begin
  227.               if hp^.unitname^=s then
  228.                 begin
  229.                    { the unit is already registered   }
  230.                    { and this means that the unit     }
  231.                    { is already compiled              }
  232.                    { else there is a cyclic unit use  }
  233.                    if assigned(hp^.symtable) then
  234.                      st:=punitsymtable(hp^.symtable)
  235.                    else
  236.                     begin
  237.                     { recompile the unit ? }
  238.                       if (not current_module^.in_implementation) and (hp^.in_implementation) then
  239.                        Message(unit_f_circular_unit_reference);
  240.                     end;
  241.                    break;
  242.                 end;
  243.               { the next unit }
  244.               hp:=pmodule(hp^.next);
  245.            end;
  246.  
  247.        { no error and the unit isn't loaded }
  248.          if not(assigned(hp)) and (st=nil) then
  249.            begin
  250.               { generates a new unit info record }
  251.               hp:=new(pmodule,init(s,true));
  252.               { now we can register the unit }
  253.               loaded_units.insert(hp);
  254.  
  255.               current_module:=hp;
  256.               { force build ? }
  257.               if (hp^.do_compile) or (hp^.sources_avail and do_build) then
  258.                 begin
  259.                    { we needn't the ppufile }
  260.                    if assigned(hp^.ppufile) then
  261.                      begin
  262.                         dispose(hp^.ppufile,done);
  263.                         hp^.ppufile:=nil;
  264.                      end;
  265.                    if not(hp^.sources_avail) then
  266.                     Message1(unit_f_cant_compile_unit,hp^.unitname^)
  267.                    else
  268.                     begin
  269.                        if assigned(old_current_module^.current_inputfile) then
  270.                          old_current_module^.current_inputfile^.tempclose;
  271.                        compile(hp^.mainsource^,compile_system);
  272.                       if (not old_current_module^.compiled) and assigned(old_current_module^.current_inputfile) then
  273.                          old_current_module^.current_inputfile^.tempreopen;
  274.                     end;
  275.                 end
  276.               else
  277.                 begin
  278.                 { only reassemble ? }
  279.                   if (hp^.do_assemble) then
  280.                    begin
  281.                      a:=new(PAsmFile,Init(hp^.asmfilename^));
  282.                      a^.DoAssemble;
  283.                      dispose(a,Done);
  284.                    end;
  285.                  { we should know there the PPU file else it's an error and
  286.                    we can't load the unit }
  287.                   if hp^.ppufile^.name^<>'' then
  288.                     begin
  289.                       if (hp^.flags and uf_in_library)=0 then
  290.                        Linker.AddObjectFile(hp^.objfilename^);
  291.                       load_ppu(old_current_module,hp,compile_system);
  292.                     end;
  293.                 end;
  294.  
  295.               { register the unit _once_ }
  296.               usedunits.concat(new(pused_unit,init(hp,0)));
  297.               { the unit is written, so we can set the symtable type }
  298.               { to unitsymtable, else we get some dupid errors       }
  299.               { this is not the right place because of the           }
  300.               { ready label                                          }
  301.               { psymtable(hp^.symtable)^.symtabletype:=unitsymtable; }
  302.               { placed at this end of proc_unit                      }
  303.               psymtable(hp^.symtable)^.unitid:=0;
  304.               { reset the unitnumbers for the other units }
  305.               pu:=pused_unit(old_current_module^.used_units.first);
  306.               while assigned(pu) do
  307.                 begin
  308.                    psymtable(pu^.u^.symtable)^.unitid:=pu^.unitid;
  309.                    pu:=pused_unit(pu^.next);
  310.                 end;
  311.            end
  312.          else
  313.            if assigned(hp) and (st=nil) then
  314.              begin
  315.                 { we have to compile the unit again, but it is already inserted !!}
  316.                 { we may have problem with the lost symtable !! }
  317.                 current_module:=hp;
  318.                 { we must preserve the unit chain }
  319.                 nextmodule:=pmodule(hp^.next);
  320.                 { we have to cleanup a little }
  321.                 hp^.special_done;
  322.                 new(hs);
  323.                 hs^:=hp^.mainsource^;
  324.                 hp^.init(hs^,true);
  325.                 dispose(hs);
  326.                 { we must preserve the unit chain }
  327.                 hp^.next:=nextmodule;
  328.                 if assigned(hp^.ppufile) then
  329.                  load_ppu(old_current_module,hp,compile_system)
  330.                 else
  331.                  begin
  332.                    if assigned(old_current_module^.current_inputfile) then
  333.                      old_current_module^.current_inputfile^.tempclose;
  334.                    Message1(parser_d_compiling_second_time,hp^.mainsource^);
  335.                    compile(hp^.mainsource^,compile_system);
  336.                    if (not old_current_module^.compiled) and assigned(old_current_module^.current_inputfile) then
  337.                      old_current_module^.current_inputfile^.tempreopen;
  338.                  end;
  339.                 current_module^.compiled:=true;
  340.              end;
  341.          { set the old module }
  342.          current_module:=old_current_module;
  343.          { the current module uses the unit hp }
  344.          current_module^.used_units.concat(new(pused_unit,init(hp,0)));
  345.          pused_unit(current_module^.used_units.last)^.in_uses:=in_uses;
  346.          if in_uses and not current_module^.in_implementation then
  347.            pused_unit(current_module^.used_units.last)^.in_interface:=true;
  348.          loadunit:=hp;
  349.       end;
  350.  
  351.     procedure loadunits;
  352.  
  353.       var
  354.          s : stringid;
  355.          hp : pused_unit;
  356.          hp2 : pmodule;
  357.          hp3 : psymtable;
  358.          oldprocsym:Pprocsym;
  359.  
  360.       begin
  361.          oldprocsym:=aktprocsym;
  362.          consume(_USES);
  363. {$ifdef DEBUG}
  364.          test_symtablestack;
  365. {$endif DEBUG}
  366.          repeat
  367.            s:=pattern;
  368.            consume(ID);
  369.            hp2:=loadunit(s,false,true);
  370.            if current_module^.compiled then
  371.              exit;
  372.            refsymtable^.insert(new(punitsym,init(s,hp2^.symtable)));
  373.  
  374.            if token=COMMA then
  375.             begin
  376.               pattern:='';
  377.               consume(COMMA);
  378.             end
  379.            else
  380.             break;
  381.          until false;
  382.          consume(SEMICOLON);
  383.  
  384.          { now insert the units in the symtablestack }
  385.          hp:=pused_unit(current_module^.used_units.first);
  386.          { set the symtable to systemunit so it gets reorderd correctly }
  387.          symtablestack:=systemunit;
  388.          while assigned(hp) do
  389.            begin
  390. {$IfDef GDB}
  391.               if (cs_debuginfo in aktswitches) and
  392.                 not hp^.is_stab_written then
  393.                 begin
  394.                    punitsymtable(hp^.u^.symtable)^.concattypestabto(debuglist);
  395.                    hp^.is_stab_written:=true;
  396.                    hp^.unitid:=psymtable(hp^.u^.symtable)^.unitid;
  397.                 end;
  398. {$EndIf GDB}
  399.               if hp^.in_uses then
  400.                 begin
  401.                    hp3:=symtablestack;
  402.                    while assigned(hp3) do
  403.                      begin
  404.                         { insert units only once ! }
  405.                         if hp^.u^.symtable=hp3 then
  406.                           break;
  407.                         hp3:=hp3^.next;
  408.                         { unit isn't inserted }
  409.                         if hp3=nil then
  410.                           begin
  411.                              psymtable(hp^.u^.symtable)^.next:=symtablestack;
  412.                              symtablestack:=psymtable(hp^.u^.symtable);
  413. {$ifdef CHAINPROCSYMS}
  414.                              symtablestack^.chainprocsyms;
  415. {$endif CHAINPROCSYMS}
  416. {$ifdef DEBUG}
  417.                              test_symtablestack;
  418. {$endif DEBUG}
  419.                           end;
  420.                      end;
  421.                 end;
  422.               hp:=pused_unit(hp^.next);
  423.            end;
  424.           aktprocsym:=oldprocsym;
  425.       end;
  426.  
  427.       procedure parse_uses(symt:Psymtable);
  428.  
  429.       begin
  430.          if token=_USES then
  431.            begin
  432.               current_module^.in_implementation:=true;
  433.               symt^.symtabletype:=unitsymtable;
  434.               loadunits;
  435.               symt^.symtabletype:=globalsymtable;
  436. {$ifdef DEBUG}
  437.               test_symtablestack;
  438. {$endif DEBUG}
  439.            end;
  440.       end;
  441.  
  442.     procedure proc_unit;
  443.  
  444.       var
  445.          unitname : stringid;
  446. {$ifdef GDB}
  447.          { several defs to simulate more or less C++ objects for GDB }
  448.          vmtdef : precdef;
  449.          pvmtdef : ppointerdef;
  450.          vmtarraydef : parraydef;
  451.          vmtsymtable : psymtable;
  452. {$endif GDB}
  453.          names:Tstringcontainer;
  454.          p : psymtable;
  455.          unitst : punitsymtable;
  456.          pu : pused_unit;
  457.          { the output ppufile is written to this path }
  458.          s1,s2,s3:^string; {Saves stack space, but only eats heap
  459.                             space when there is a lot of heap free.}
  460.  
  461.       begin
  462.          consume(_UNIT);
  463.  
  464.          stringdispose(current_module^.objfilename);
  465.          stringdispose(current_module^.ppufilename);
  466.        { create filenames and check unit name }
  467.          new(s1);
  468.          new(s2);
  469.          new(s3);
  470.          s1^:=FixFileName(current_module^.current_inputfile^.path^+current_module^.current_inputfile^.name^);
  471.          current_module^.objfilename:=stringdup(s1^+target_info.objext);
  472.          current_module^.ppufilename:=stringdup(s1^+target_info.unitext);
  473.  
  474.          s1^:=upper(pattern);
  475.          s2^:=upper(target_info.system_unit);
  476.          s3^:=upper(current_module^.current_inputfile^.name^);
  477.          if (cs_compilesystem in aktswitches)  then
  478.           begin
  479.             if (cs_check_unit_name in aktswitches) and
  480.                ((length(pattern)>8) or (s1^<>s2^) or (s1^<>s3^)) then
  481.                 Message1(unit_e_illegal_unit_name,s1^);
  482.           end
  483.          else
  484.           if (s1^=s2^) then
  485.            Message(unit_w_switch_us_missed);
  486.          dispose(s3);
  487.          dispose(s2);
  488.          dispose(s1);
  489.  
  490.        { add object }
  491.          Linker.AddObjectFile(current_module^.objfilename^);
  492.  
  493.          unitname:=pattern;
  494.  
  495.          consume(ID);
  496.          consume(SEMICOLON);
  497.          consume(_INTERFACE);
  498.  
  499.          { this should be placed after uses !!}
  500. {$ifndef UseNiceNames}
  501.          procprefix:='_'+unitname+'$$';
  502. {$else UseNiceNames}
  503.          procprefix:='_'+tostr(length(unitname))+lowercase(unitname)+'_';
  504. {$endif UseNiceNames}
  505.  
  506.          parse_only:=true;
  507.  
  508.          { generate now the global symboltable }
  509.          p:=new(punitsymtable,init(globalsymtable,unitname));
  510.          refsymtable:=p;
  511.          unitst:=punitsymtable(p);
  512.  
  513.          { set the symbol table for the current unit }
  514.          { this must be set later for interdependency }
  515.          { current_module^.symtable:=psymtable(p); }
  516.  
  517.          { a unit compiled at command line must be inside the loaded_unit list }
  518.          if (compile_level=1) then
  519.            begin
  520.               current_module^.unitname:=stringdup(unitname);
  521.               loaded_units.insert(current_module);
  522.               if cs_unit_to_lib in initswitches then
  523.                 begin
  524.                 current_module^.flags:=current_module^.flags or uf_in_library;
  525.                 if cs_shared_lib in initswitches then
  526.                   current_module^.flags:=current_module^.flags or uf_shared_library;
  527.                 end;
  528.            end;
  529.  
  530.  
  531.          { insert qualifier for the system unit (allows system.writeln) }
  532.          if not(cs_compilesystem in aktswitches) then
  533.            begin
  534.               { insert the system unit }
  535.               { it is allways the first }
  536.               systemunit^.next:=nil;
  537.               symtablestack:=systemunit;
  538.               refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  539.  
  540.               if token=_USES then
  541.                 begin
  542.                    unitst^.symtabletype:=unitsymtable;
  543.                    loadunits;
  544.                    { has it been compiled at a higher level ?}
  545.                    if current_module^.compiled then
  546.                      exit;
  547.                    unitst^.symtabletype:=globalsymtable;
  548.                 end;
  549.  
  550.               { ... but insert the symbol table later }
  551.               p^.next:=symtablestack;
  552.               symtablestack:=p;
  553.            end
  554.          else
  555.          { while compiling a system unit, some types are directly inserted }
  556.            begin
  557.               p^.next:=symtablestack;
  558.               symtablestack:=p;
  559.               p^.insert(new(ptypesym,init('longint',s32bitdef)));
  560.               p^.insert(new(ptypesym,init('ulong',u32bitdef)));
  561.               p^.insert(new(ptypesym,init('void',voiddef)));
  562.               p^.insert(new(ptypesym,init('char',cchardef)));
  563. {$ifdef i386}
  564.               p^.insert(new(ptypesym,init('s64real',c64floatdef)));
  565. {$endif i386}
  566.               p^.insert(new(ptypesym,init('s80real',s80floatdef)));
  567.               p^.insert(new(ptypesym,init('cs32fixed',s32fixeddef)));
  568.               p^.insert(new(ptypesym,init('byte',u8bitdef)));
  569.               p^.insert(new(ptypesym,init('string',cstringdef)));
  570.               p^.insert(new(ptypesym,init('word',u16bitdef)));
  571.               p^.insert(new(ptypesym,init('boolean',booldef)));
  572.               p^.insert(new(ptypesym,init('void_pointer',voidpointerdef)));
  573.               p^.insert(new(ptypesym,init('file',cfiledef)));
  574. {$ifdef i386}
  575.               p^.insert(new(ptypesym,init('REAL',new(pfloatdef,init(s64real)))));
  576.               p^.insert(new(ptypesym,init('COMP',new(pfloatdef,init(s64bit)))));
  577.               p^.insert(new(ptypesym,init('EXTENDED',new(pfloatdef,init(s80real)))));
  578. {$endif}
  579. {$ifdef m68k}
  580.               { internal definitions }
  581.               p^.insert(new(ptypesym,init('s32real',c64floatdef)));
  582.               { mappings... }
  583.               p^.insert(new(ptypesym,init('REAL',new(pfloatdef,init(s32real)))));
  584.               if (cs_fp_emulation) in aktswitches then
  585.                    p^.insert(new(ptypesym,init('DOUBLE',new(pfloatdef,init(s32real)))))
  586.               else
  587.                    p^.insert(new(ptypesym,init('DOUBLE',new(pfloatdef,init(s64real)))));
  588. {              p^.insert(new(ptypesym,init('COMP',new(pfloatdef,init(s32real)))));}
  589.               if (cs_fp_emulation) in aktswitches then
  590.                    p^.insert(new(ptypesym,init('EXTENDED',new(pfloatdef,init(s32real)))))
  591.               else
  592.                    p^.insert(new(ptypesym,init('EXTENDED',new(pfloatdef,init(s80real)))));
  593. {$endif}
  594.               p^.insert(new(ptypesym,init('SINGLE',new(pfloatdef,init(s32real)))));
  595.               p^.insert(new(ptypesym,init('POINTER',new(ppointerdef,init(voiddef)))));
  596.               p^.insert(new(ptypesym,init('STRING',cstringdef)));
  597.               p^.insert(new(ptypesym,init('BOOLEAN',new(porddef,init(bool8bit,0,1)))));
  598.               p^.insert(new(ptypesym,init('CHAR',new(porddef,init(uchar,0,255)))));
  599.               p^.insert(new(ptypesym,init('TEXT',new(pfiledef,init(ft_text,nil)))));
  600.               p^.insert(new(ptypesym,init('CARDINAL',new(porddef,init(u32bit,0,$ffffffff)))));
  601.               p^.insert(new(ptypesym,init('FIXED',new(pfloatdef,init(f32bit)))));
  602.               p^.insert(new(ptypesym,init('FIXED16',new(pfloatdef,init(f16bit)))));
  603.               p^.insert(new(ptypesym,init('TYPEDFILE',new(pfiledef,init(ft_typed,voiddef)))));
  604.               { !!!!!
  605.               p^.insert(new(ptypesym,init('COMP',new(porddef,init(s64bit,0,0)))));
  606.               p^.insert(new(ptypesym,init('SINGLE',new(porddef,init(s32real,0,0)))));
  607.               p^.insert(new(ptypesym,init('EXTENDED',new(porddef,init(s80real,0,0)))));
  608.               p^.insert(new(ptypesym,init('FILE',new(pfiledef,init(ft_untyped,nil)))));
  609.               }
  610.               { Add a type for virtual method tables in lowercase }
  611.               { so it isn't reachable!                            }
  612. {$ifdef GDB}
  613.               vmtsymtable:=new(psymtable,init(recordsymtable));
  614.               vmtdef:=new(precdef,init(vmtsymtable));
  615.               pvmtdef:=new(ppointerdef,init(vmtdef));
  616.               vmtsymtable^.insert(new(pvarsym,init('parent',pvmtdef)));
  617.               vmtsymtable^.insert(new(pvarsym,init('length',globaldef('longint'))));
  618.               vmtsymtable^.insert(new(pvarsym,init('mlength',globaldef('longint'))));
  619.               vmtarraydef:=new(parraydef,init(0,1,s32bitdef));
  620.               vmtarraydef^.definition := voidpointerdef;
  621.               vmtsymtable^.insert(new(pvarsym,init('__pfn',vmtarraydef)));
  622.               p^.insert(new(ptypesym,init('__vtbl_ptr_type',vmtdef)));
  623.               p^.insert(new(ptypesym,init('pvmt',pvmtdef)));
  624.               vmtarraydef:=new(parraydef,init(0,1,s32bitdef));
  625.               vmtarraydef^.definition := pvmtdef;
  626.               p^.insert(new(ptypesym,init('vtblarray',vmtarraydef)));
  627.               insertinternsyms(p);
  628. {$endif GDB}
  629.            end;
  630.  
  631.          { displaced for inter-dependency considerations }
  632.          current_module^.symtable:=psymtable(p);
  633.  
  634.          constsymtable:=symtablestack;
  635.          { ... parse the declarations }
  636.          read_interface_declarations;
  637.          consume(_IMPLEMENTATION);
  638.  
  639.          parse_only:=false;
  640.          refsymtable^.number_defs;
  641.  
  642. {$ifdef GDB}
  643.          { add all used definitions even for implementation}
  644.          if (cs_debuginfo in aktswitches) then
  645.            begin
  646.               { all types }
  647.               punitsymtable(refsymtable)^.concattypestabto(debuglist);
  648.               { and all local symbols}
  649.               refsymtable^.concatstabto(debuglist);
  650.            end;
  651. {$endif GDB}
  652.          { for interdependent units
  653.          the crc is included in the ppufile
  654.          but it is not known when writing the first ppufile
  655.          so I tried to add a fake writing of the ppu
  656.          just to get the CRC
  657.          but the result is different for the real CRC
  658.          it calculates after, I don't know why
  659.  
  660.          Answer:
  661.          -------
  662.          When reading the interface part, the compiler assumes
  663.          that all registers are modified by a procedure
  664.          usedinproc:=$ff !
  665.          If the definition is read, the compiler determines
  666.          the used registers and write the correct value
  667.          to usedinproc
  668.  
  669.          only_calculate_crc:=true;
  670.          writeunitas(current_module^.current_inputfile^.path^+current_module^.current_inputfile^.name^+
  671.                      +'.PPS',punitsymtable(symtablestack));
  672.          only_calculate_crc:=false;
  673.          }
  674.          { generates static symbol table }
  675.          p:=new(punitsymtable,init(staticsymtable,unitname));
  676.          refsymtable:=p;
  677.  
  678.          {Generate a procsym.}
  679.          aktprocsym:=new(Pprocsym,init(unitname+'_init'));
  680.          aktprocsym^.definition:=new(Pprocdef,init);
  681.          aktprocsym^.definition^.options:=aktprocsym^.definition^.options or pounitinit;
  682.          aktprocsym^.definition^.setmangledname(unitname+'_init');
  683.  
  684.          {The generated procsym has a local symtable. Discard it and turn
  685.           it into the static one.}
  686.          dispose(aktprocsym^.definition^.localst,done);
  687.          aktprocsym^.definition^.localst:=p;
  688.  
  689.          names.init;
  690.          names.insert(unitname+'_init');
  691.  
  692.          { testing !!!!!!!!! }
  693.          { we set the interface part as a unitsymtable  }
  694.          { for the case we need to compile another unit }
  695.  
  696.          { remove the globalsymtable from the symtable stack }
  697.          { to reinsert it after loading the implementation units }
  698.          symtablestack:=unitst^.next;
  699.  
  700.          parse_uses(unitst);
  701.  
  702.          { duplicated here to be sure }
  703. {$ifndef UseNiceNames}
  704.          procprefix:='_'+unitname+'$$';
  705. {$else UseNiceNames}
  706.          procprefix:='_'+tostr(length(unitname))+lowercase(unitname)+'_';
  707. {$endif UseNiceNames}
  708.  
  709.          { but reinsert the global symtable as lasts }
  710.          unitst^.next:=symtablestack;
  711.          symtablestack:=unitst;
  712.  
  713. {$ifdef DEBUG}
  714.          test_symtablestack;
  715. {$endif DEBUG}
  716.          constsymtable:=symtablestack;
  717.  
  718. {$ifdef Splitheap}
  719.          if testsplit then
  720.            begin
  721.               Split_Heap;
  722.               allow_special:=true;
  723.               Switch_to_temp_heap;
  724.            end;
  725. {$endif Splitheap}
  726.  
  727. {$ifdef Splitheap}
  728.          { it will report all crossings }
  729.          allow_special:=false;
  730. {$endif Splitheap}
  731.          { set some informations }
  732.          procinfo.retdef:=voiddef;
  733.          procinfo._class:=nil;
  734.          procinfo.call_offset:=8;
  735.  
  736.          { for temporary values }
  737.          procinfo.framepointer:=frame_pointer;
  738.  
  739.          { clear flags }
  740.          procinfo.flags:=0;
  741.  
  742.          {Reset the codegenerator.}
  743.          codegen_newprocedure;
  744.  
  745.          names.insert('INIT$$'+unitname);
  746.  
  747.          compile_proc_body(names,true,false);
  748.  
  749.          codegen_doneprocedure;
  750.  
  751.          consume(POINT);
  752.  
  753.          names.done;
  754.  
  755.          { size of the static data }
  756.          datasize:=symtablestack^.datasize;
  757.  
  758.          { unsed static symbols ? }
  759.          symtablestack^.allsymbolsused;
  760.  
  761. {$ifdef GDB}
  762.          { add all used definitions even for implementation}
  763.          if (cs_debuginfo in aktswitches) then
  764.             begin
  765.                   { all types }
  766.                   punitsymtable(symtablestack)^.concattypestabto(debuglist);
  767.                   { and all local symbols}
  768.                   symtablestack^.concatstabto(debuglist);
  769.             end;
  770. {$endif GDB}
  771.  
  772.          current_module^.in_implementation:=false;
  773.          { deletes all symtables generated in the implementation part }
  774.          while symtablestack^.symtabletype<>globalsymtable do
  775.            dellexlevel;
  776.  
  777.          { tests, if all forwards are resolved }
  778.          symtablestack^.check_forwards;
  779.          symtablestack^.symtabletype:=unitsymtable;
  780.          punitsymtable(symtablestack)^.is_stab_written:=false;
  781.  
  782.          {Write out the unit if the compile was succesfull.}
  783.          if errorcount=0 then
  784.           writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack));
  785.  
  786.          pu:=pused_unit(usedunits.first);
  787.          while assigned(pu) do
  788.            begin
  789.               punitsymtable(pu^.u^.symtable)^.is_stab_written:=false;
  790.               pu:=pused_unit(pu^.next);
  791.            end;
  792.          inc(datasize,symtablestack^.datasize);
  793.       end;
  794.  
  795.     procedure proc_program(islibrary : boolean);
  796.  
  797.       var
  798.          i : longint;
  799.          st : psymtable;
  800.          programname : stringid;
  801.          names:Tstringcontainer;
  802.       begin
  803.          { Trying to compile the system unit... }
  804.          { if no unit defined... then issue a   }
  805.          { fatal error (avoids pointer problems)}
  806.          { when referencing the non-existant    }
  807.          { system unit.                         }
  808.          if (cs_compilesystem in aktswitches) then
  809.          Begin
  810.            if token<>_UNIT then
  811.             Message1(scan_f_syn_expected,'UNIT');
  812.            consume(_UNIT);
  813.          end;
  814.  
  815.          parse_only:=false;
  816.          programname:='';
  817.  
  818.          if islibrary then
  819.            begin
  820.               consume(_LIBRARY);
  821.               programname:=pattern;
  822.               consume(ID);
  823.               consume(SEMICOLON);
  824.            end
  825.          else
  826.            { is there an program head ? }
  827.            if token=_PROGRAM then
  828.            begin
  829.               consume(_PROGRAM);
  830.               programname:=pattern;
  831.               consume(ID);
  832.               if token=LKLAMMER then
  833.                 begin
  834.                    consume(LKLAMMER);
  835.                    idlist;
  836.                    consume(RKLAMMER);
  837.                 end;
  838.               consume(SEMICOLON);
  839.            end;
  840.  
  841.          { insert after the unit symbol tables the static symbol table }
  842.          { of the program                                              }
  843.          st:=new(punitsymtable,init(staticsymtable,programname));
  844.  
  845.          {Generate a procsym.}
  846.          aktprocsym:=new(Pprocsym,init('main'));
  847.          aktprocsym^.definition:=new(Pprocdef,init);
  848.          aktprocsym^.definition^.options:=aktprocsym^.definition^.options or poproginit;
  849.          aktprocsym^.definition^.setmangledname(target_info.Cprefix+'main');
  850.          {The localst is a local symtable. Change it into the static
  851.           symtable.}
  852.          dispose(aktprocsym^.definition^.localst,done);
  853.          aktprocsym^.definition^.localst:=st;
  854.  
  855.          names.init;
  856.          names.insert('program_init');
  857.  
  858.          refsymtable:=st;
  859.  
  860.          {Insert the symbols of the system unit into the stack of symbol
  861.           tables.}
  862.          symtablestack:=systemunit;
  863.          systemunit^.next:=nil;
  864.          refsymtable^.insert(new(punitsym,init('SYSTEM',systemunit)));
  865.  
  866.          {Load the units used by the program we compile.}
  867.          if token=_USES then loadunits;
  868.  
  869.          {Insert the name of the main program into the symbol table.}
  870.          if programname<>'' then
  871.            st^.insert(new(pprogramsym,init(programname)));
  872.  
  873.          { ...is also constsymtable, this is the symtable where }
  874.          { the elements of enumeration types are inserted       }
  875.          constsymtable:=st;
  876.  
  877.          codegen_newprocedure;
  878.  
  879.          { set some informations about the main program }
  880.          procinfo.retdef:=voiddef;
  881.          procinfo._class:=nil;
  882.          procinfo.call_offset:=8;
  883.  
  884.          {Set the framepointer of the program initialization to the
  885.           default framepointer (EBP on i386).}
  886.          procinfo.framepointer:=frame_pointer;
  887.  
  888.          { clear flags }
  889.          procinfo.flags:=0;
  890.  
  891.          procprefix:='';
  892.          in_except_block:=false;
  893.  
  894.  
  895.          {The program intialization needs an alias, so it can be called
  896.           from the bootstrap code.}
  897.          case target_info.target of
  898.             target_GO32V1,
  899.             target_GO32V2,
  900.             target_OS2,
  901.             target_WIN32,
  902.             target_AMIGA,
  903.             target_ATARI:
  904.               names.insert('_main');
  905.             target_LINUX:
  906.               names.insert('main');
  907.          end;
  908.          if target_info.target=target_PalmOS then
  909.            names.insert('PilotMain');
  910.  
  911.          names.insert('PASCALMAIN');
  912.  
  913.          compile_proc_body(names,true,false);
  914.  
  915.          codegen_doneprocedure;
  916.  
  917.          Linker.AddObjectFile(current_module^.unitname^);
  918.          current_module^.linkofiles.insert(current_module^.unitname^);
  919.  
  920.         { On the Macintosh Classic M68k Architecture   }
  921.         { The Heap variable is simply a POINTER to the }
  922.         { real HEAP. The HEAP must be set up by the RTL }
  923.         { and must store the pointer in this value.    }
  924.         {On OS/2 the heap is also intialized by the RTL. We do
  925.          not  output a pointer.}
  926.          if target_info.target<>target_OS2 then
  927.             if (target_info.target = target_MAC68k) then
  928.                 bsssegment^.concat(new(pai_datablock,init_global('HEAP',4)))
  929.             else
  930.                 bsssegment^.concat(new(pai_datablock,init_global('HEAP',heapsize)));
  931.          if target_info.target in [target_GO32V2,target_ATARI] then
  932.            begin
  933.               { stacksize can be specified }
  934.               datasegment^.concat(new(pai_symbol,init_global('__stklen')));
  935.               datasegment^.concat(new(pai_const,init_32bit(stacksize)));
  936.            end;
  937.          if (target_info.target=target_WIN32) then
  938.            begin
  939.               { generate the last entry for the imports directory }
  940.               if not(assigned(importssection)) then
  941.                 importssection:=new(paasmoutput,init);
  942.               { $3 ensure that it is the last entry, all other entries }
  943.               { are written to $2                                      }
  944.               importssection^.concat(new(pai_section,init('.idata$3')));
  945.               for i:=1 to 5 do
  946.                 importssection^.concat(new(pai_const,init_32bit(0)));
  947.            end;
  948.  
  949.          {I prefer starting with a heapsize of 256K in OS/2. The heap can
  950.           grow later until the size specified on the command line. Allocating
  951.           four megs at once can hurt performance when more programs are in
  952.           memory.}
  953. {$ifdef i386}
  954.          datasegment^.concat(new(pai_symbol,init_global('HEAPSIZE')));
  955. {$endif i386}
  956. {$ifdef m68k}
  957.          datasegment^.concat(new(pai_symbol,init_global('HEAP_SIZE')));
  958. {$endif m68k}
  959.          if target_info.target=target_OS2 then
  960.           heapsize:=256*1024;
  961.          datasegment^.concat(new(pai_const,init_32bit(heapsize)));
  962.          datasize:=symtablestack^.datasize;
  963.  
  964.          names.done;
  965.  
  966.          consume(POINT);
  967.  
  968.          symtablestack^.check_forwards;
  969.          symtablestack^.allsymbolsused;
  970.       end;
  971.  
  972. end.
  973. {
  974.   $Log: pmodules.pas,v $
  975.   Revision 1.2.2.6  1998/09/14 18:58:09  carl
  976.     * correct endian for reading of CRC
  977.  
  978.   Revision 1.2.2.5  1998/08/18 13:37:43  carl
  979.     + compile time stack setting for ATARI
  980.     + main support for m68k targets
  981.  
  982.   Revision 1.2.2.4  1998/08/13 17:41:25  florian
  983.     + some stuff for the PalmOS added
  984.  
  985.   Revision 1.2.2.3  1998/08/05 10:33:52  pierre
  986.     * added tempclose and temp reopen
  987.       to be able to compile lots of dependent units
  988.  
  989.   Revision 1.2.2.2  1998/07/08 12:05:56  carl
  990.     * HEAPSIZE replaced by HEA_PSIZE for m68k targets
  991.  
  992.   Revision 1.2.2.1  1998/04/06 16:21:10  peter
  993.     * carl and mine bugfixes from the mainbranch applied
  994.  
  995.   Revision 1.2  1998/03/30 15:53:01  florian
  996.     * last changes before release:
  997.        - gdb fixed
  998.        - ratti386 warning removed (about unset function result)
  999.  
  1000.   Revision 1.1.1.1  1998/03/25 11:18:15  root
  1001.   * Restored version
  1002.  
  1003.   Revision 1.43  1998/03/20 23:31:34  florian
  1004.     * bug0113 fixed
  1005.     * problem with interdepened units fixed ("options.pas problem")
  1006.     * two small extensions for future AMD 3D support
  1007.  
  1008.   Revision 1.42  1998/03/11 22:22:52  florian
  1009.     * Fixed circular unit uses, when the units are not in the current dir (from Peter)
  1010.     * -i shows correct info, not <lf> anymore (from Peter)
  1011.     * linking with shared libs works again (from Peter)
  1012.  
  1013.   Revision 1.41  1998/03/10 17:19:29  peter
  1014.     * fixed bug0108
  1015.     * better linebreak scanning (concentrated in nextchar(), it supports
  1016.       #10, #13, #10#13, #13#10
  1017.  
  1018.   Revision 1.40  1998/03/10 16:27:42  pierre
  1019.     * better line info in stabs debug
  1020.     * symtabletype and lexlevel separated into two fields of tsymtable
  1021.     + ifdef MAKELIB for direct library output, not complete
  1022.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  1023.       working
  1024.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  1025.       working
  1026.  
  1027.   Revision 1.39  1998/03/10 01:17:24  peter
  1028.     * all files have the same header
  1029.     * messages are fully implemented, EXTDEBUG uses Comment()
  1030.     + AG... files for the Assembler generation
  1031.  
  1032.   Revision 1.38  1998/03/05 22:43:50  florian
  1033.     * some win32 support stuff added
  1034.  
  1035.   Revision 1.37  1998/03/04 01:35:08  peter
  1036.     * messages for unit-handling and assembler/linker
  1037.     * the compiler compiles without -dGDB, but doesn't work yet
  1038.     + -vh for Hint
  1039.  
  1040.   Revision 1.36  1998/03/03 23:18:45  florian
  1041.     * ret $8 problem with unit init/main program fixed
  1042.  
  1043.   Revision 1.35  1998/03/02 13:38:48  peter
  1044.     + importlib object
  1045.     * doesn't crash on a systemunit anymore
  1046.     * updated makefile and depend
  1047.  
  1048.   Revision 1.34  1998/03/02 01:49:04  peter
  1049.     * renamed target_DOS to target_GO32V1
  1050.     + new verbose system, merged old errors and verbose units into one new
  1051.       verbose.pas, so errors.pas is obsolete
  1052.  
  1053.   Revision 1.33  1998/03/01 22:46:20  florian
  1054.     + some win95 linking stuff
  1055.     * a couple of bugs fixed:
  1056.       bug0055,bug0058,bug0059,bug0064,bug0072,bug0093,bug0095,bug0098
  1057.  
  1058.   Revision 1.32  1998/02/28 09:30:58  florian
  1059.     + writing of win32 import section added
  1060.  
  1061.   Revision 1.31  1998/02/28 03:57:08  carl
  1062.     + replaced target_info.short_name by target_info.target (a bit faster)
  1063.  
  1064.   Revision 1.30  1998/02/27 09:25:58  daniel
  1065.   * Changed symtable handling so no junk symtable is put on the symtablestack.
  1066.  
  1067.   Revision 1.28  1998/02/24 14:20:54  peter
  1068.     + tstringcontainer.empty
  1069.     * ld -T option restored for linux
  1070.     * libraries are placed before the objectfiles in a .PPU file
  1071.     * removed 'uses link' from files.pas
  1072.  
  1073.   Revision 1.27  1998/02/24 00:19:19  peter
  1074.     * makefile works again (btw. linux does like any char after a \ )
  1075.     * removed circular unit with assemble and files
  1076.     * fixed a sigsegv in pexpr
  1077.     * pmodule init unit/program is the almost the same, merged them
  1078.  
  1079.   Revision 1.26  1998/02/22 23:55:18  peter
  1080.     * small fix
  1081.  
  1082.   Revision 1.25  1998/02/22 23:03:28  peter
  1083.     * renamed msource->mainsource and name->unitname
  1084.     * optimized filename handling, filename is not seperate anymore with
  1085.       path+name+ext, this saves stackspace and a lot of fsplit()'s
  1086.     * recompiling of some units in libraries fixed
  1087.     * shared libraries are working again
  1088.     + $LINKLIB <lib> to support automatic linking to libraries
  1089.     + libraries are saved/read from the ppufile, also allows more libraries
  1090.       per ppufile
  1091.  
  1092.   Revision 1.24  1998/02/22 18:51:06  carl
  1093.     * where the heck did the HEAP for m68k go??????? REINSTATED
  1094.  
  1095.   Revision 1.23  1998/02/21 05:50:14  carl
  1096.     * bugfix of crash with Us switch
  1097.  
  1098.   Revision 1.22  1998/02/19 00:11:08  peter
  1099.     * fixed -g to work again
  1100.     * fixed some typos with the scriptobject
  1101.  
  1102.   Revision 1.21  1998/02/17 21:20:57  peter
  1103.     + Script unit
  1104.     + __EXIT is called again to exit a program
  1105.     - target_info.link/assembler calls
  1106.     * linking works again for dos
  1107.     * optimized a few filehandling functions
  1108.     * fixed stabs generation for procedures
  1109.  
  1110.   Revision 1.20  1998/02/16 12:51:38  michael
  1111.   + Implemented linker object
  1112.  
  1113.   Revision 1.19  1998/02/14 01:45:29  peter
  1114.     * more fixes
  1115.     - pmode target is removed
  1116.     - search_as_ld is removed, this is done in the link.pas/assemble.pas
  1117.     + findexe() to search for an executable (linker,assembler,binder)
  1118.  
  1119.   Revision 1.18  1998/02/13 22:26:37  peter
  1120.     * fixed a few SigSegv's
  1121.     * INIT$$ was not written for linux!
  1122.     * assembling and linking works again for linux and dos
  1123.     + assembler object, only attasmi3 supported yet
  1124.     * restore pp.pas with AddPath etc.
  1125.  
  1126.   Revision 1.17  1998/02/13 10:35:27  daniel
  1127.   * Made Motorola version compilable.
  1128.   * Fixed optimizer
  1129.  
  1130.   Revision 1.16  1998/02/12 17:19:22  florian
  1131.     * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1132.       also that aktswitches isn't a pointer)
  1133.  
  1134.   Revision 1.15  1998/02/12 11:50:28  daniel
  1135.   Yes! Finally! After three retries, my patch!
  1136.  
  1137.   Changes:
  1138.  
  1139.   Complete rewrite of psub.pas.
  1140.   Added support for DLL's.
  1141.   Compiler requires less memory.
  1142.   Platform units for each platform.
  1143.  
  1144.   Revision 1.14  1998/01/30 17:31:26  pierre
  1145.     * bug of cyclic symtablestack fixed
  1146.  
  1147.   Revision 1.13  1998/01/28 13:48:49  michael
  1148.   + Initial implementation for making libs from within FPC. Not tested, as compiler does not run
  1149.  
  1150.   Revision 1.12  1998/01/19 15:46:25  peter
  1151.   * fixed INIT$$lowercase generation
  1152.  
  1153.   Revision 1.11  1998/01/19 09:32:28  michael
  1154.   * Shared Lib and GDB/RHIDE Bufixes from Peter Vreman.
  1155.  
  1156.   Revision 1.10  1998/01/17 01:57:39  michael
  1157.   + Start of shared library support. First working version.
  1158.  
  1159.   Revision 1.9  1998/01/16 18:03:17  florian
  1160.     * small bug fixes, some stuff of delphi styled constructores added
  1161.  
  1162.   Revision 1.8  1998/01/13 23:11:15  florian
  1163.     + class methods
  1164.  
  1165.   Revision 1.7  1998/01/13 17:13:09  michael
  1166.   * File time handling and file searching is now done in an OS-independent way,
  1167.     using the new file treating functions in globals.pas.
  1168.  
  1169.   Revision 1.6  1998/01/13 16:16:03  pierre
  1170.     *  bug in interdependent units handling
  1171.        - primary unit was not in loaded_units list
  1172.        - current_module^.symtable was assigned too early
  1173.        - donescanner must not call error if the compilation
  1174.        of the unit was done at a higher level.
  1175.  
  1176.   Revision 1.5  1998/01/12 13:03:32  florian
  1177.     + parsing of class methods implemented
  1178.  
  1179.   Revision 1.4  1998/01/11 10:54:24  florian
  1180.     + generic library support
  1181.  
  1182.   Revision 1.3  1998/01/11 04:17:36  carl
  1183.   + floating point support for m68k
  1184.  
  1185.   Revision 1.2  1998/01/09 09:10:01  michael
  1186.   + Initial implementation, second try
  1187.  
  1188. }
  1189.